1.根据我们常用的web.xml里,我们找到的org.springframework.web.context.ContextLoaderListener。web.xml如下


<?xml version="1.0" encoding="UTF-8"?>
<web-app
        version="3.0"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <display-name>moon</display-name>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener> 
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath*:applicationContext.xml
        </param-value>
    </context-param>
</web-app>
  1. 其实ContextLoaderListener是一个ServletContextListener,一个web容器的监听器。根据其父类org.springframework.web.context.ContextLoader初始化的策略配置,找到类目录下面的ContextLoader.properties文件。里面配置着一个Spring上下文类。
# Default WebApplicationContext implementation class for ContextLoader.
# Used as fallback when no explicit context implementation has been specified as context-param.
# Not meant to be customized by application developers.

org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext

额外知识点:
参考《ClassPathResource知识点》

  1. 加载策略资源(ContextLoader.properties)后,web容器启动时会调用ContextLoaderListener的contextInitialized方法。
  2. contextInitialized方法里初始化ContextLoader.properties配置的org.springframework.web.context.support.XmlWebApplicationContext,这个初始化过程有点长。
    4.1 从ServletContext获取对象springcontext对象,如果存在则抛异常。key=org.springframework.web.context.WebApplicationContext.ROOT
    4.2 从ContextLoader.properties获取className=org.springframework.web.context.support.XmlWebApplicationContext
    4.3 通过ClassUtils工具实例化spring的ApplicationContext,我们能够看出他是使用ContextLoader类的类加载器,这里有个可以弄个知识点《ClassUtils知识点》
ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader())

4.4 XmlWebApplicationContext实例化时,其一些列父类也将初始化和实例化(我稍微地简化说,具体的可以看源码):

层次 类名 作用
第0层 org.springframework.web.context.support.XmlWebApplicationContext 定义默认配置文件,如/WEB-INF/applicationContext.xml
第1层 org.springframework.web.context.support.AbstractRefreshableWebApplicationContext 声明了ServletContext servletContext和ServletConfig servletConfig
第2层 org.springframework.context.support.AbstractRefreshableConfigApplicationContext 此时就跟web没多大关系了,定义了配置变量String[] configLocations
第3层 org.springframework.context.support.AbstractRefreshableApplicationContext 此层就重要了,定义了DefaultListableBeanFactory beanFactory
第4层 org.springframework.context.support.AbstractApplicationContext 此层定义了父context,还有ApplicationContext的其他配置等,refresh()方法
第5层 org.springframework.core.io.DefaultResourceLoader 此层与ApplicationContext没多大关系,从包名也能看出,声明了ClassLoader
第6层(最后一层) org.springframework.core.io.ResourceLoader spring的作者的注释是Strategy interface for loading resources,嗯哈,大概猜是使用策略模式的接口
  1. 实例化完XmlWebApplicationContext类后,就开始做点事情了。在ContextLoader里,有个方法configureAndRefreshWebApplicationContext(cwac, servletContext),从方法名就能看出是配置和刷新ApplicationContext。
    5.1 设置ServletContext,参考第1层
    5.2 设置configLocations,参考第2层,这里又一个知识点《StringUtils知识点》
    5.3 调用AbstractRefreshableWebApplicationContext的createEnvironment()方法来初始化StandardServletEnvironment对象。参考知识点《StandardServletEnvironment知识点》
    5.4 调用StandardServletEnvironment对象initPropertySources(ServletContext servletContext, ServletConfig servletConfig)方法来获取web容器所有配置信息。配置信息都在放在StandardServletEnvironment对象的MutablePropertySources对象里。
    5.5 customizeContext(sc, wac)自定义初始化applicationContext的一些信息,里面是获取实现org.springframework.context.ApplicationContextInitializer接口的一些方法调用。一个知识点也诞生《ApplicationContextInitializer知识点》

    5.6 重头戏来了,refresh ApplicationContext!!!,调用第4层的refresh()方法。

      5.6.1 第一步:加载ServletContext和ServletConfig参数,并使用PropertySourcesPropertyResolver校验是否有必须的配置缺失,可参考知识点《PropertySourcesPropertyResolver知识点》。
      
      5.6.2 第二步:实例化BeanFactory,交给子类AbstractRefreshableApplicationContext来实例化(参考第3层),实例化了org.springframework.beans.factory.support.DefaultListableBeanFactory对象作为变量beanFactory的值。并配置是否允许覆盖bean和是否允许循环引用,默认都是否。
      
      
      5.6.3 第三步:第3层AbstractRefreshableApplicationContext去loadBeanDefinitions,loadBeanDefinitions方法被子类XmlWebApplicationContext覆写了,创建org.springframework.beans.factory.xml.XmlBeanDefinitionReader对象进行加载Bean的定义。这个是重点核心的知识点,参考《XmlBeanDefinitionReader知识点》。  
       
      看到这里应该知道每一层ApplicationContext的作用吧,一层一层往上递进
      
      5.6.4 第四步: //TODO 正在研读XmlBeanDefinitionReader
    
  2. //TODO

电脑杂技集团
208 声望32 粉丝

这家伙好像很懂计算机~